package com.hice.demo.sbdbra.common.util.email;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.mail.*;
import javax.mail.Flags.Flag;
import javax.mail.Message.RecipientType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

public class ReceiveMailUtils {
    private static Logger logger = LoggerFactory.getLogger(ReceiveMailUtils.class);
    private MimeMessage mimeMessage = null;
    private String saveAttachPath = "";
    private StringBuffer bodyText = new StringBuffer();
    private String dateFormat = "yy-MM-dd HH:mm";

    public ReceiveMailUtils() {
    }

    public ReceiveMailUtils(MimeMessage mimeMessage) {
        this.mimeMessage = mimeMessage;
        logger.info("创建一个ReceiveEmail对象....");
    }

    public void setMimeMessage(MimeMessage mimeMessage) {
        this.mimeMessage = mimeMessage;
        logger.info("设置一个MimeMessage对象...");
    }

    public String getFrom()
            throws Exception {
        InternetAddress[] address = (InternetAddress[]) (InternetAddress[]) this.mimeMessage.getFrom();
        String from = address[0].getAddress();
        if (from == null) {
            from = "";
            logger.info("无法知道发送者.");
        }

        return from;
    }

    public String getMailAddress(String type)
            throws Exception {
        String mailAddr = "";
        String addType = type.toUpperCase();

        InternetAddress[] address = null;
        if ((addType.equals("TO")) || (addType.equals("CC")) || (addType.equals("BCC"))) {
            if (addType.equals("TO")) {
                address = (InternetAddress[]) (InternetAddress[]) this.mimeMessage
                        .getRecipients(RecipientType.TO);
            } else if (addType.equals("CC")) {
                address = (InternetAddress[]) (InternetAddress[]) this.mimeMessage
                        .getRecipients(RecipientType.CC);
            } else {
                address = (InternetAddress[]) (InternetAddress[]) this.mimeMessage
                        .getRecipients(RecipientType.BCC);
            }

            if (address != null) {
                for (int i = 0; i < address.length; i++) {
                    String emailAddr = address[i].getAddress();
                    if (emailAddr == null) {
                        emailAddr = "";
                    } else {
                        logger.info("转换之前的emailAddr: " + emailAddr);
                        emailAddr = MimeUtility.decodeText(emailAddr);
                        logger.info("转换之后的emailAddr: " + emailAddr);
                    }
                    String personal = address[i].getPersonal();
                    if (personal == null) {
                        personal = "";
                    } else {
                        logger.info("转换之前的personal: " + personal);
                        personal = MimeUtility.decodeText(personal);
                        logger.info("转换之后的personal: " + personal);
                    }
                    String compositeto = personal + "<" + emailAddr + ">";
                    logger.info("完整的邮件地址：" + compositeto);
                    mailAddr = mailAddr + "," + compositeto;
                }
                mailAddr = mailAddr.substring(1);
            }
        } else {
            throw new Exception("错误的电子邮件类型!");
        }
        return mailAddr;
    }

    public String getSubject()
            throws MessagingException {
        String subject = "";
        try {
            logger.info("转换前的subject：" + this.mimeMessage.getSubject());
            subject = MimeUtility.decodeText(this.mimeMessage.getSubject());
            logger.info("转换后的subject: " + this.mimeMessage.getSubject());
            if (subject == null)
                subject = "";
        } catch (Exception exce) {
            exce.printStackTrace();
        }
        return subject;
    }

    public String getSentDate()
            throws Exception {
        Date sentDate = this.mimeMessage.getSentDate();
        logger.info("发送日期 原始类型: " + this.dateFormat);
        SimpleDateFormat format = new SimpleDateFormat(this.dateFormat);
        String strSentDate = format.format(sentDate);
        logger.info("发送日期 可读类型: " + strSentDate);
        return strSentDate;
    }

    public String getBodyText() {
        return this.bodyText.toString();
    }

    public void getMailContent(Part part)
            throws Exception {
        String contentType = part.getContentType();

        logger.info("邮件的MimeType类型: " + contentType);

        int nameIndex = contentType.indexOf("name");

        boolean conName = false;

        if (nameIndex != -1) {
            conName = true;
        }

        logger.info("邮件内容的类型:　" + contentType);

        if ((part.isMimeType("text/plain")) && (!conName)) {
            this.bodyText.append((String) part.getContent());
        } else if ((part.isMimeType("text/html")) && (!conName)) {
            this.bodyText.append((String) part.getContent());
        } else if (part.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) part.getContent();
            int counts = multipart.getCount();
            for (int i = 0; i < counts; i++)
                getMailContent(multipart.getBodyPart(i));
        } else if (part.isMimeType("message/rfc822")) {
            getMailContent((Part) part.getContent());
        }
    }

    public boolean getReplySign()
            throws MessagingException {
        boolean replySign = false;

        String[] needReply = this.mimeMessage.getHeader("Disposition-Notification-To");

        if (needReply != null) {
            replySign = true;
        }
        if (replySign)
            logger.info("该邮件需要回复");
        else {
            logger.info("该邮件不需要回复");
        }
        return replySign;
    }

    public String getMessageId()
            throws MessagingException {
        String messageID = this.mimeMessage.getMessageID();
        logger.info("邮件ID: " + messageID);
        return messageID;
    }

    public boolean isNew()
            throws MessagingException {
        boolean isNew = false;
        Flags flags = this.mimeMessage.getFlags();
        Flag[] flag = flags.getSystemFlags();
        logger.info("flags的长度:　" + flag.length);
        for (int i = 0; i < flag.length; i++) {
            if (flag[i] == Flag.SEEN) {
                isNew = true;
                logger.info("seen email...");
            }
        }

        return isNew;
    }

    public boolean isContainAttach(Part part)
            throws Exception {
        boolean attachFlag = false;

        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                BodyPart mPart = mp.getBodyPart(i);
                String disposition = mPart.getDisposition();
                if ((disposition != null) && (
                        (disposition
                                .equals("attachment")) ||
                                (disposition
                                        .equals("inline")))) {
                    attachFlag = true;
                } else if (mPart.isMimeType("multipart/*")) {
                    attachFlag = isContainAttach(mPart);
                } else {
                    String conType = mPart.getContentType();

                    if (conType.toLowerCase().indexOf("application") != -1)
                        attachFlag = true;
                    if (conType.toLowerCase().indexOf("name") != -1)
                        attachFlag = true;
                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            attachFlag = isContainAttach((Part) part.getContent());
        }
        return attachFlag;
    }

    public void saveAttachMent(Part part)
            throws Exception {
        String fileName = "";
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                BodyPart mPart = mp.getBodyPart(i);
                String disposition = mPart.getDisposition();
                if ((disposition != null) && (
                        (disposition
                                .equals("attachment")) ||
                                (disposition
                                        .equals("inline")))) {
                    fileName = mPart.getFileName();
                    if (fileName.toLowerCase().indexOf("gb2312") != -1) {
                        fileName = MimeUtility.decodeText(fileName);
                    }
                    saveFile(fileName, mPart.getInputStream());
                } else if (mPart.isMimeType("multipart/*")) {
                    saveAttachMent(mPart);
                } else {
                    fileName = mPart.getFileName();
                    if ((fileName == null) ||
                            (fileName
                                    .toLowerCase().indexOf("GB2312") == -1)) continue;
                    fileName = MimeUtility.decodeText(fileName);
                    saveFile(fileName, mPart.getInputStream());
                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            saveAttachMent((Part) part.getContent());
        }
    }

    public void setAttachPath(String attachPath) {
        this.saveAttachPath = attachPath;
    }

    public void setDateFormat(String format)
            throws Exception {
        this.dateFormat = format;
    }

    public String getAttachPath() {
        return this.saveAttachPath;
    }

    private void saveFile(String fileName, InputStream in)
            throws Exception {
        String osName = System.getProperty("os.name");
        String storeDir = getAttachPath();
        String separator = "";
        if (osName == null) {
            osName = "";
        }
        if (osName.toLowerCase().indexOf("win") != -1) {
            separator = "\\";
            if ((storeDir == null) || (storeDir.equals("")))
                storeDir = "c:\\tmp";
        } else {
            separator = "/";
            storeDir = "/tmp";
        }
        File storeFile = new File(storeDir + separator + fileName);
        logger.info("附件的保存地址:　" + storeFile.toString());

        BufferedOutputStream bos = null;
        BufferedInputStream bis = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(storeFile));
            bis = new BufferedInputStream(in);
            int c;
            while ((c = bis.read()) != -1) {
                bos.write(c);
                bos.flush();
            }
        } catch (Exception exception) {
            exception.printStackTrace();
            throw new Exception("文件保存失败!");
        } finally {
            bos.close();
            bis.close();
        }
    }

    public static String receiveMail(String account, String password) {
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        try {
            String host = account.split("@")[1];
            host = "pop." + host;
            Store store = session.getStore("pop3");
            store.connect(host, account, password);
            Folder folder = store.getFolder("INBOX");
            folder.open(1);
            Message[] message = folder.getMessages(folder.getMessageCount(), folder
                    .getMessageCount());
            ReceiveMailUtils re = null;
            if (message.length > 0) {
                re = new ReceiveMailUtils((MimeMessage) message[0]);
                logger.info("接收邮件　发送人地址:　" + re.getFrom());
                return re.getFrom();
            }
        } catch (Exception e) {
            logger.error("接收邮件异常", e);
        }
        return "";
    }

    public static void main(String[] args)
            throws Exception {
        String host = "pop.163.com";
        String username = "eyuntx_server@163.com";
        String password = "qtvvpkqkksitlwpe";

        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        Store store = session.getStore("pop3");
        store.connect(host, username, password);

        Folder folder = store.getFolder("INBOX");
        folder.open(1);
        Message[] message = folder.getMessages(folder.getMessageCount(), folder
                .getMessageCount());
        logger.info("邮件数量:　" + message.length);
        ReceiveMailUtils re = null;

        for (int i = 0; i < message.length; i++) {
            re = new ReceiveMailUtils((MimeMessage) message[i]);
            logger.info("邮件　" + i + "　主题:　" + re.getSubject());
            logger.info("邮件　" + i + "　发送时间:　" + re.getSentDate());
            logger.info("邮件　" + i + "　是否需要回复:　" + re.getReplySign());
            logger.info("邮件　" + i + "　是否已读:　" + re.isNew());
            logger.info("邮件　" + i + "　是否包含附件:　" + re
                    .isContainAttach(message[i]));

            logger.info("邮件　" + i + "　发送人地址:　" + re.getFrom());
            logger.info("邮件　" + i + "　收信人地址:　" + re.getMailAddress("to"));
            logger.info("邮件　" + i + "　抄送:　" + re.getMailAddress("cc"));
            logger.info("邮件　" + i + "　暗抄:　" + re.getMailAddress("bcc"));
            re.setDateFormat("yy年MM月dd日　HH:mm");
            logger.info("邮件　" + i + "　发送时间:　" + re.getSentDate());
            logger.info("邮件　" + i + "　邮件ID:　" + re.getMessageId());
            re.getMailContent(message[i]);
            logger.info("邮件　" + i + "　正文内容:　\r\n" + re.getBodyText());
            re.setAttachPath("e:\\");
            re.saveAttachMent(message[i]);
        }
    }
}